#include "PhysicsSimulator.h"

namespace steam
{
	namespace wheel
	{

		PhysicsSimulator::PhysicsSimulator( int rigidBodyCount, int animatedBodyCount )
{
			neSimulatorSizeInfo sizeInfo;

			sizeInfo.rigidBodiesCount = rigidBodyCount;
			sizeInfo.animatedBodiesCount = animatedBodyCount;
			s32 totalBody = sizeInfo.rigidBodiesCount + sizeInfo.animatedBodiesCount;
			sizeInfo.geometriesCount = totalBody;
			sizeInfo.overlappedPairsCount = totalBody * (totalBody - 1) / 2;

			neV3 gravity;
			gravity.Set(0.0f, -9.8f, 0.0f);
			m_simulator = neSimulator::CreateSimulator(sizeInfo, NULL, &gravity);
		}

		PhysicsSimulator::~PhysicsSimulator()
		{
			neSimulator::DestroySimulator(m_simulator);
		}

		void PhysicsSimulator::advance(float elapsedTime)
		{
			m_simulator->Advance(elapsedTime);
		}

		IBox* PhysicsSimulator::createBox( BoxInfo info, SimulateType simType )
		{
			Box* box = NULL;
			if (simType == SIMULATE_AUTO) // RigidBody
			{
				neRigidBody* rigidBody = m_simulator->CreateRigidBody();
				m_rigidBodies.push_back(rigidBody);

				neGeometry* geom = rigidBody->AddGeometry();
				geom->SetBoxSize(info.Size.x, info.Size.y, info.Size.z);

				rigidBody->UpdateBoundingInfo();
				rigidBody->SetInertiaTensor(neBoxInertiaTensor(info.Size.x, info.Size.y, info.Size.z, info.Mass));
				rigidBody->SetMass(info.Mass);

				neV3 pos; pos.Set(info.Position.x, info.Position.y, info.Position.z);
				rigidBody->SetPos(pos);

				box = new Box(info, simType);
				box->setRigidBody(rigidBody);
			}
			else if (simType == SIMULATE_MANUAL)
			{
				neAnimatedBody* animBody = m_simulator->CreateAnimatedBody();
				m_animatedBodies.push_back(animBody);

				neGeometry* geom = animBody->AddGeometry();
				geom->SetBoxSize(info.Size.x, info.Size.y, info.Size.z);

				animBody->UpdateBoundingInfo();

				neV3 pos; pos.Set(info.Position.x, info.Position.y, info.Position.z);
				animBody->SetPos(pos);

				box = new Box(info, simType);
				box->setAnimatedBody(animBody);
			}
			else
			{
				ASSERT(false);
			}
			return box;
		}

		Sphere* PhysicsSimulator::createSphere( SphereInfo info, SimulateType simType )
		{
			if (simType == SIMULATE_AUTO)// RigidBody
			{
				neRigidBody* rigidBody = m_simulator->CreateRigidBody();
				m_rigidBodies.push_back(rigidBody);
			}
			else if (simType == SIMULATE_MANUAL)
			{
				neAnimatedBody* animBody = m_simulator->CreateAnimatedBody();
				m_animatedBodies.push_back(animBody);
			}
			else
			{
				ASSERT(false);
			}
			return NULL;
		}

		Cylinder* PhysicsSimulator::createCylinder( CylinderInfo info, SimulateType simType )
		{
			if (simType == SIMULATE_AUTO)// RigidBody
			{
				neRigidBody* rigidBody = m_simulator->CreateRigidBody();
				m_rigidBodies.push_back(rigidBody);
			}
			else if (simType == SIMULATE_MANUAL)
			{
				neAnimatedBody* animBody = m_simulator->CreateAnimatedBody();
				m_animatedBodies.push_back(animBody);
			}
			else
			{
				ASSERT(false);
			}
			return NULL;
		}

	}
}